package com.bird.common.utils.tkmybatis;

import com.bird.common.utils.StringUtil;
import tk.mybatis.mapper.weekend.Fn;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.reflection.Reflections;

/**
 * 包装tk mybatis的查询类，一行代码搞定
 *
 * @author: 625
 * @version: 2020年06月09日 14:54
 */
public class TK<T> extends Weekend<T> {

	/**
	 * 开始，查询的列规范
	 *
	 * @param clazz
	 * @param exists  - true时，如果字段不存在就抛出异常，false时，如果不存在就不使用该字段的条件
	 * @param notNull - true时，如果值为空，就会抛出异常，false时，如果为空就不使用该字段的条件
	 * @param <T>
	 * @return
	 */
	public static <T> TK<T> select(Class<T> clazz, Boolean exists, boolean notNull) {
		return new TK<T>(clazz, exists, notNull);
	}

	/**
	 * 开始，查询的列规范
	 *
	 * @param clazz
	 * @param exists - true时，如果字段不存在就抛出异常，false时，如果不存在就不使用该字段的条件
	 * @param <T>
	 * @return
	 */
	public static <T> TK<T> select(Class<T> clazz, Boolean exists) {
		return new TK<T>(clazz, exists, Boolean.FALSE);
	}

	/**
	 * 开始，查询的列规范
	 *
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	public static <T> TK<T> select(Class<T> clazz) {
		return new TK<T>(clazz, Boolean.TRUE);
	}

	/**
	 * 指定要查询的列
	 *
	 * @param properties 驼峰或者下划线都可以
	 * @return
	 */
	public TK<T> column(String... properties) {
		properties = StringUtil.toCamelCase(properties);
		return (TK<T>) selectProperties(properties);
	}

	/**
	 * 排除要查询的列
	 *
	 * @param properties
	 * @return
	 */
	public TK<T> columnExclude(String... properties) {
		properties = StringUtil.toCamelCase(properties);
		return (TK<T>) excludeProperties(properties);
	}

	/**
	 * 排序设置
	 *
	 * @param property
	 * @return
	 */
	public TK<T> orderBy(Fn<T, Object> property) {
		String propertyStr = Reflections.fnToFieldName(property);
		this.ORDERBY.orderBy(propertyStr);
		return this;
	}

	/**
	 * 排序设置
	 *
	 * @return
	 */
	public TK<T> desc() {
		this.ORDERBY.desc();
		return this;
	}

	/**
	 * 排序设置
	 *
	 * @return
	 */
	public TK<T> asc() {
		this.ORDERBY.asc();
		return this;
	}

	/**
	 * 排序设置
	 *
	 * @param orderByClause
	 * @return
	 */
	public TK<T> orderByClause(String orderByClause) {
		this.setOrderByClause(orderByClause);
		return this;
	}

	/**
	 * 排序设置
	 *
	 * @param limit 返回记录数
	 * @return
	 */
	public TK<T> limit(int limit) {
		this.setOrderByClause(this.getOrderByClause() + " limit " + limit);
		return this;
	}

	/**
	 * 加写锁
	 *
	 * @return
	 */
	public TK<T> forUpdate() {
		setForUpdate(true);
		return this;
	}

	/**
	 * 去重
	 *
	 * @return
	 */
	public TK<T> distinct() {
		setDistinct(true);
		return this;
	}

	/**
	 * 构造要查询的条件
	 */
	public TKCriteria<T, Object> where() {
		return (TKCriteria<T, Object>) this.createCriteria();
	}

	private TK(Class<T> entityClass) {
		super(entityClass);
	}

	private TK(Class<T> entityClass, boolean exists) {
		super(entityClass, exists);
	}

	private TK(Class<T> entityClass, boolean exists, boolean notNull) {
		super(entityClass, exists, notNull);
	}

	@Override
	public TKCriteria<T, Object> createCriteriaAddOn() {
		TKCriteria<T, Object> weekendCriteria = new TKCriteria(this.propertyMap, this.exists, this.notNull, this);
		return weekendCriteria;
	}

	@Override
	protected Criteria createCriteriaInternal() {
		return createCriteriaAddOn();
	}
}
